/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.acegisecurity.ui.webapp;

import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;

import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;

import org.acegisecurity.ui.AbstractProcessingFilter;

import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

/**
 * Processes an authentication form.
 * <p>
 * Login forms must present two parameters to this filter: a username and
 * password. The parameter names to use are contained in the static fields
 * {@link #ACEGI_SECURITY_FORM_USERNAME_KEY} and
 * {@link #ACEGI_SECURITY_FORM_PASSWORD_KEY}.
 * </p>
 * 
 * <p>
 * <b>Do not use this class directly.</b> Instead configure
 * <code>web.xml</code> to use the {@link
 * org.acegisecurity.util.FilterToBeanProxy}.
 * </p>
 * 
 * @author Ben Alex guanhw 
 * @author Colin Sampaleanu
 * @version $Id: AuthenticationProcessingFilter.java 2110 2007-09-14 14:32:19Z
 *          luke_t $
 */
public class AuthenticationProcessingFilter extends AbstractProcessingFilter {
	// ~ Static fields/initializers
	// =====================================================================================

	public static final String	ACEGI_SECURITY_FORM_USERNAME_KEY	= "j_username";
	public static final String	ACEGI_SECURITY_FORM_PASSWORD_KEY	= "j_password";
	public static final String	ACEGI_SECURITY_FORM_VALIDCODE_KEY	= "j_valid_code";
	public static final String	ACEGI_SECURITY_LAST_USERNAME_KEY	= org.acegisecurity.allways.Constants.ACEGI_SECURITY_LAST_USERNAME_KEY;

	// ~ Methods
	// ========================================================================================================

	public Authentication attemptAuthentication ( HttpServletRequest request )
			throws AuthenticationException {
		String username = obtainUsername( request );
		String password = obtainPassword( request );

		if ( username == null ) {
			username = "";
		}

		if ( password == null ) {
			password = "";
		}

		username = username.trim();
		
		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( username, password );

		// Place the last username attempted into HttpSession for views
		request.getSession().setAttribute( ACEGI_SECURITY_LAST_USERNAME_KEY , username );

		// Allow subclasses to set the "details" property
		setDetails( request, authRequest );
		
		return this.getAuthenticationManager().authenticate( authRequest );
	}

	/**
	 * This filter by default responds to <code>/j_acegi_security_check</code>.
	 * 
	 * @return the default
	 */
	public String getDefaultFilterProcessesUrl ( ) {
		return "/j_acegi_security_check";
	}

	public void init ( FilterConfig filterConfig ) throws ServletException {
	}

	/**
	 * Enables subclasses to override the composition of the password, such as
	 * by including additional values and a separator.
	 * <p>
	 * This might be used for example if a postcode/zipcode was required in
	 * addition to the password. A delimiter such as a pipe (|) should be used
	 * to separate the password and extended value(s). The
	 * <code>AuthenticationDao</code> will need to generate the expected
	 * password in a corresponding manner.
	 * </p>
	 * 
	 * @param request
	 *            so that request attributes can be retrieved
	 * 
	 * @return the password that will be presented in the
	 *         <code>Authentication</code> request token to the
	 *         <code>AuthenticationManager</code>
	 */
	protected String obtainPassword ( HttpServletRequest request ) {
		return request.getParameter( ACEGI_SECURITY_FORM_PASSWORD_KEY );
	}

	/**
	 * Enables subclasses to override the composition of the username, such as
	 * by including additional values and a separator.
	 * 
	 * @param request
	 *            so that request attributes can be retrieved
	 * 
	 * @return the username that will be presented in the
	 *         <code>Authentication</code> request token to the
	 *         <code>AuthenticationManager</code>
	 */
	protected String obtainUsername ( HttpServletRequest request ) {
		return request.getParameter( ACEGI_SECURITY_FORM_USERNAME_KEY );
	}

	
	protected String obtainValidCode ( HttpServletRequest request ) {
		return request.getParameter( ACEGI_SECURITY_FORM_VALIDCODE_KEY );
	}
	
	
	/**
	 * Provided so that subclasses may configure what is put into the
	 * authentication request's details property.
	 * 
	 * @param request
	 *            that an authentication request is being created for
	 * @param authRequest
	 *            the authentication request object that should have its details
	 *            set
	 */
	protected void setDetails ( HttpServletRequest request ,
			UsernamePasswordAuthenticationToken authRequest ) {
		authRequest.setDetails( authenticationDetailsSource
				.buildDetails( request ) );
	}
}
